package org.fast.develop.logicflow.runtime.executor;

import cn.hutool.core.util.StrUtil;
import org.fast.develop.logicflow.core.meta.base.Element;
import org.fast.develop.logicflow.core.meta.base.task.Task;
import org.fast.develop.logicflow.core.meta.shape.properties.ServiceTaskProperties;
import org.fast.develop.logicflow.core.meta.shape.task.ServiceTask;
import org.fast.develop.logicflow.runtime.exception.LogicFlowException;
import org.fast.develop.logicflow.runtime.node.LogicFlowNode;
import org.fast.develop.logicflow.runtime.task.delegate.TaskListener;

/**
 * @author 莫寅
 * @createTime 2022-11-24 22:25
 * @desc：
 */
public class TaskExecutor {


    private TaskListenerCreator taskListenerCreator;

    public TaskExecutor(TaskListenerCreator taskListenerCreator) {
        this.taskListenerCreator = taskListenerCreator;
    }

    public void execute(LogicFlowNode logicFlowNode){
        Element element = logicFlowNode.getElement();
        if(!(element instanceof Task)){
            return;
        }

        if(element instanceof ServiceTask){
            ServiceTask serviceTask = (ServiceTask)element;
            ServiceTaskProperties serviceTaskProperties = (ServiceTaskProperties) serviceTask.getProperties();

            if(serviceTaskProperties != null && StrUtil.isNotBlank(serviceTaskProperties.getClassName())){

                String className = serviceTaskProperties.getClassName();
                TaskListener taskListener = newInstanceTaskListener(className);
                taskListener.notify(logicFlowNode);
            }

        }
    }

    public TaskListener newInstanceTaskListener(String className){
        try {
            Class aClass = Class.forName(className);
            if(!asSubclass(aClass, TaskListener.class)){
                throw new LogicFlowException(StrUtil.format("{}:未继承：{}", className, TaskListener.class));
            }

            TaskListener taskListener = null;
            if(taskListenerCreator != null){
                taskListener = taskListenerCreator.get(aClass);
            }else{
                taskListener = (TaskListener) aClass.newInstance();
            }
            return taskListener;
        } catch (ClassNotFoundException e) {
            throw new LogicFlowException(StrUtil.format("{}：监听器未找到", className), e);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

        return null;
    }



    public static boolean asSubclass(Class subClass, Class superClass){
        try{
            subClass.asSubclass(superClass);
            return true;
        }catch (Exception e){
            return false;
        }
    }
}
